﻿package com.cb.model
{
	/**
	 * @author blackcj.com - Christopher Black - September 13, 2010
	 * 
	 * Resources: 
	 * http://www.emanueleferonato.com/2009/05/18/understanding-how-box2d-manages-boundaries/
	 * http://www.box2d.org/manual.html
	 * http://box2dflash.sourceforge.net/
	 *
	 */
	 
	import flash.events.EventDispatcher;
	import flash.events.Event;
	import flash.display.MovieClip;
	import com.cb.model.vo.Object2dVO;
	import flash.geom.Rectangle;
	import flash.utils.Timer;
	import Box2D.Collision.*;
	import Box2D.Collision.Shapes.*;
	import Box2D.Common.Math.*;
	import Box2D.Dynamics.*;
	
	import com.cb.Constants;
	import flash.display.Sprite;
	import com.cb.view.WorldView;
	import flash.display.Stage;
		
	public class WorldModel extends EventDispatcher
	{
		private static var _instance:WorldModel
		private var _worldView:WorldView;
		protected var debug_mode:Boolean;
		protected var world:b2World;
		protected var body:b2Body;
		protected var running:Boolean = false;
		
		public function WorldModel()
		{
			var gravity:b2Vec2 = new b2Vec2(0,9.8);
			var worldAABB:b2AABB = new b2AABB();
			
			worldAABB.lowerBound.Set(-100,-100);
			worldAABB.upperBound.Set(100,100);
			world = new b2World(gravity, false);
			
			_worldView = new WorldView();

		}

		/*
		* PUBLIC FUNCTIONS
		*/  
		public function add2dObject(obj2dVO:Object2dVO):void
		{
			var body:b2Body = world.CreateBody(obj2dVO.bodyDef);
			body.CreateFixture(obj2dVO.fixtureDef);
			_worldView.addChild(obj2dVO.bodyDef.userData);
		}
		
		public function get worldView():Sprite
		{
			return _worldView;
		}
		
		public function updateDimensions(w:int, h:int):void
		{
			_worldView.updateDimensions(w, h);
		}

		public static function getInstance():WorldModel
      	{
         	if(_instance == null)
        	{
            	_instance = new WorldModel();
       		}
         	return _instance;
      	}		
		
		public function update():void {
			world.Step(Constants.TIMESTEP, Constants.ITERATIONS, Constants.ITERATIONS);
			world.ClearForces();
			world.DrawDebugData();
			
			for (var bb:b2Body = world.GetBodyList(); bb; bb=bb.GetNext()) {
				if (bb.GetUserData() is Sprite) {
					var sprite:Sprite = bb.GetUserData() as Sprite;
					sprite.x = bb.GetPosition().x * Constants.PHYS_SCALE;
					sprite.y = bb.GetPosition().y * Constants.PHYS_SCALE;
					sprite.rotation = bb.GetAngle() * 180 / Math.PI;
				}
			}  

		}
	}
}